/*
 * Copyright (c) 2003-2004, Inversoft, All Rights Reserved
 */
package org.emergent.antbite.savant;


import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


/**
 * <p>
 * This class is a toolkit for handling artifact operations.
 * </p>
 *
 * @author Brian Pontarelli
 */
public class ArtifactTools {

    public static final String OPEN_TAG = "<dependencies>\n";
    public static final String CLOSE_TAG = "</dependencies>";


    /**
     * Updates the given artifact with its dependencies by parsing the XML
     * dependency file (if one exists).
     *
     * @param   artifact The artifact to update
     * @param   file The File to read the XML dependency information from.
     * @throws  SavantException If building, parsing or content failed or was
     *          invalid
     */
    public static Document resolveArtifactDependencies(Artifact artifact,
            File file)
    throws SavantException {
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            DocumentBuilder xmlBuilder =
                DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = xmlBuilder.parse(bis);
            NodeList list = doc.getElementsByTagName("artifact");
            for (int i = 0; i < list.getLength(); i++) {
                Node node = list.item(i);
                NamedNodeMap attrs = node.getAttributes();
                Node group = attrs.getNamedItem("group");
                if (group == null) {
                    throw new SavantException("Artifact deps XML missing " +
                        "group attribute [" + artifact.getName() + "]");
                }

                Node name = attrs.getNamedItem("name");
                if (name == null) {
                    throw new SavantException("Artifact deps XML missing " +
                        "name attribute [" + artifact.getName() + "]");
                }

                Node projName = attrs.getNamedItem("projectname");
                if (projName == null) {
                    throw new SavantException("Artifact deps XML missing " +
                        "projectname attribute [" + artifact.getName() + "]");
                }

                Node type = attrs.getNamedItem("type");
                if (type == null) {
                    throw new SavantException("Artifact deps XML missing " +
                        "type attribute [" + artifact.getName() + "]");
                }

                Node version = attrs.getNamedItem("version");

                Artifact dep = new Artifact();
                dep.setGroup(group.getNodeValue());
                dep.setName(name.getNodeValue());
                dep.setProjectname(projName.getNodeValue());
                dep.setType(type.getNodeValue());
                dep.setVersion( (version == null ? null : version.getNodeValue()) );

                artifact.addDependency(dep);
            }

            return doc;
        } catch (IOException ioe) {
            throw new SavantException("Unable to parse artifact dependency XML " +
                "for artifact [" + artifact + "]", ioe);
        } catch (ParserConfigurationException pce) {
            throw new SavantException("Unable to parse artifact dependency XML " +
                "for artifact [" + artifact + "]", pce);
        } catch (SAXException se) {
            throw new SavantException("Unable to parse artifact dependency XML " +
                "for artifact [" + artifact + "]", se);
        }
    }

    /**
     * Generates a temporary file that contains dependency XML which includes all
     * of the artifacts given.
     *
     * @param   artifacts The set of artifacts to include in the XML.
     * @return  The temp file and never null.
     * @throws  SavantException If the temp could not be created, or the XML could
     *          not be written.
     */
    public static final File generateXML(Set artifacts) throws SavantException {
        BufferedWriter bos = null;
        try {
            File tmp = File.createTempFile("savant", "deps");
            bos = new BufferedWriter(new FileWriter(tmp));

            // Write the open tag
            bos.write(OPEN_TAG);
            for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) {
                Artifact artifact = (Artifact) iterator.next();
                bos.write("  <artifact group=\"" + artifact.getGroup() +
                    "\" projectname=\"" + artifact.getProjectname() + "\" name=\"" +
                    artifact.getName() + "\" version=\"" + artifact.getVersion() +
                    "\" type=\"" + artifact.getType() + "\"/>\n");
            }

            bos.write(CLOSE_TAG);
            return tmp;
        } catch (IOException ioe) {
            throw new SavantException(ioe);
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException ioe) {
                    throw new SavantException(ioe);
                }
            }
        }
    }
}